﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MsTestUtilities.Utilities;

namespace MsTestUtilities.RowTests
{
    public partial class Expector<T1, E>
    {
		private TestCaseCollection<T1, E> _builder;
		ITestCase<T1, E> _testCase;

		public Expector(TestCaseCollection<T1, E> builder, ITestCase<T1, E> testCase)
		{
			_builder = builder;
			_testCase = testCase;
		}		

		public Justifier<T1, E> Expect(IExpectation<E> expectation)
		{
			_testCase.Expectation = expectation;
			return new Justifier<T1, E>(_builder, _testCase);
		}

		public Justifier<T1, E> Expect(IExpectation expectation)
		{
			return Expect(new ActionExpectationWrapper<E>(expectation));
		}

		public Justifier<T1, E> Expect(E expected)
		{
			var expectation = new Expectation<E>(expected);
			return Expect(expectation);
		}

		public Justifier<T1, E> Expect(E expected, Func<E, E, AssertionResult> asserter)
		{
			var expectation = new AsserterExpectation<E>(expected, asserter);
			return Expect(expectation);
		}
		
		public Justifier<T1, E> Do(Action<E, E> asserter, E expected)
		{
			var expectation = new StandardAssertExpectation<E>(expected, asserter);
			return Expect(expectation);
		}
		
		public Justifier<T1, E> XDo(Action<E, E> asserter, E expected)
		{
			var expectation = new StandardAssertExpectation<E>(asserter, expected);
			return Expect(expectation);
		}		

		public Justifier<T1, E> Do(Action<E> assertion)
		{
			var expectation = new StandardAssertExpectation<E>(assertion);
			return Expect(expectation);
		}

		public Justifier<T1, E> Expect(Predicate<E> expected)
		{
			var expectation = new Expectation<E>(expected);
			return Expect(expectation);
		}

		public Justifier<T1, E> Expect(Func<T1, E> transform)
		{
			Predicate<E> predicate = actual => Equals(actual, _testCase.G1); 
            return Expect(predicate);
		}

		public Justifier<T1, E> ExpectNull()
		{
			var expectation = new Expectation<E>((E a) => a == null, a => string.Format("Expected null, but got <{0}>", a));
			return Expect(expectation);
		}

		public Justifier<T1, E> ExpectNotNull()
		{
			var expectation = new Expectation<E>((E a) => a != null, a => "Expected something no null, but got null");
			return Expect(expectation);
		}

		public Justifier<T1, E> ExpectException<TException>()
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>();			
			return Expect(expectation);
		}

		public Justifier<T1, E> ExpectException<TException>(string message)
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>(message);			
			return Expect(expectation);
		}

		public Justifier<T1, E> ExpectException<TException>(Predicate<TException> predicate)
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>(predicate);			
			return Expect(expectation);
		}		
    }

    public partial class Expector<T1, T2, E>
    {
		private TestCaseCollection<T1, T2, E> _builder;
		ITestCase<T1, T2, E> _testCase;

		public Expector(TestCaseCollection<T1, T2, E> builder, ITestCase<T1, T2, E> testCase)
		{
			_builder = builder;
			_testCase = testCase;
		}		

		public Justifier<T1, T2, E> Expect(IExpectation<E> expectation)
		{
			_testCase.Expectation = expectation;
			return new Justifier<T1, T2, E>(_builder, _testCase);
		}

		public Justifier<T1, T2, E> Expect(IExpectation expectation)
		{
			return Expect(new ActionExpectationWrapper<E>(expectation));
		}

		public Justifier<T1, T2, E> Expect(E expected)
		{
			var expectation = new Expectation<E>(expected);
			return Expect(expectation);
		}

		public Justifier<T1, T2, E> Expect(E expected, Func<E, E, AssertionResult> asserter)
		{
			var expectation = new AsserterExpectation<E>(expected, asserter);
			return Expect(expectation);
		}
		
		public Justifier<T1, T2, E> Do(Action<E, E> asserter, E expected)
		{
			var expectation = new StandardAssertExpectation<E>(expected, asserter);
			return Expect(expectation);
		}
		
		public Justifier<T1, T2, E> XDo(Action<E, E> asserter, E expected)
		{
			var expectation = new StandardAssertExpectation<E>(asserter, expected);
			return Expect(expectation);
		}		

		public Justifier<T1, T2, E> Do(Action<E> assertion)
		{
			var expectation = new StandardAssertExpectation<E>(assertion);
			return Expect(expectation);
		}

		public Justifier<T1, T2, E> Expect(Predicate<E> expected)
		{
			var expectation = new Expectation<E>(expected);
			return Expect(expectation);
		}

		public Justifier<T1, T2, E> Expect(Func<T1, T2, E> transform)
		{
			Predicate<E> predicate = actual => Equals(actual, _testCase.G1); 
            return Expect(predicate);
		}

		public Justifier<T1, T2, E> ExpectNull()
		{
			var expectation = new Expectation<E>((E a) => a == null, a => string.Format("Expected null, but got <{0}>", a));
			return Expect(expectation);
		}

		public Justifier<T1, T2, E> ExpectNotNull()
		{
			var expectation = new Expectation<E>((E a) => a != null, a => "Expected something no null, but got null");
			return Expect(expectation);
		}

		public Justifier<T1, T2, E> ExpectException<TException>()
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>();			
			return Expect(expectation);
		}

		public Justifier<T1, T2, E> ExpectException<TException>(string message)
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>(message);			
			return Expect(expectation);
		}

		public Justifier<T1, T2, E> ExpectException<TException>(Predicate<TException> predicate)
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>(predicate);			
			return Expect(expectation);
		}		
    }

    public partial class Expector<T1, T2, T3, E>
    {
		private TestCaseCollection<T1, T2, T3, E> _builder;
		ITestCase<T1, T2, T3, E> _testCase;

		public Expector(TestCaseCollection<T1, T2, T3, E> builder, ITestCase<T1, T2, T3, E> testCase)
		{
			_builder = builder;
			_testCase = testCase;
		}		

		public Justifier<T1, T2, T3, E> Expect(IExpectation<E> expectation)
		{
			_testCase.Expectation = expectation;
			return new Justifier<T1, T2, T3, E>(_builder, _testCase);
		}

		public Justifier<T1, T2, T3, E> Expect(IExpectation expectation)
		{
			return Expect(new ActionExpectationWrapper<E>(expectation));
		}

		public Justifier<T1, T2, T3, E> Expect(E expected)
		{
			var expectation = new Expectation<E>(expected);
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, E> Expect(E expected, Func<E, E, AssertionResult> asserter)
		{
			var expectation = new AsserterExpectation<E>(expected, asserter);
			return Expect(expectation);
		}
		
		public Justifier<T1, T2, T3, E> Do(Action<E, E> asserter, E expected)
		{
			var expectation = new StandardAssertExpectation<E>(expected, asserter);
			return Expect(expectation);
		}
		
		public Justifier<T1, T2, T3, E> XDo(Action<E, E> asserter, E expected)
		{
			var expectation = new StandardAssertExpectation<E>(asserter, expected);
			return Expect(expectation);
		}		

		public Justifier<T1, T2, T3, E> Do(Action<E> assertion)
		{
			var expectation = new StandardAssertExpectation<E>(assertion);
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, E> Expect(Predicate<E> expected)
		{
			var expectation = new Expectation<E>(expected);
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, E> Expect(Func<T1, T2, T3, E> transform)
		{
			Predicate<E> predicate = actual => Equals(actual, _testCase.G1); 
            return Expect(predicate);
		}

		public Justifier<T1, T2, T3, E> ExpectNull()
		{
			var expectation = new Expectation<E>((E a) => a == null, a => string.Format("Expected null, but got <{0}>", a));
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, E> ExpectNotNull()
		{
			var expectation = new Expectation<E>((E a) => a != null, a => "Expected something no null, but got null");
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, E> ExpectException<TException>()
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>();			
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, E> ExpectException<TException>(string message)
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>(message);			
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, E> ExpectException<TException>(Predicate<TException> predicate)
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>(predicate);			
			return Expect(expectation);
		}		
    }

    public partial class Expector<T1, T2, T3, T4, E>
    {
		private TestCaseCollection<T1, T2, T3, T4, E> _builder;
		ITestCase<T1, T2, T3, T4, E> _testCase;

		public Expector(TestCaseCollection<T1, T2, T3, T4, E> builder, ITestCase<T1, T2, T3, T4, E> testCase)
		{
			_builder = builder;
			_testCase = testCase;
		}		

		public Justifier<T1, T2, T3, T4, E> Expect(IExpectation<E> expectation)
		{
			_testCase.Expectation = expectation;
			return new Justifier<T1, T2, T3, T4, E>(_builder, _testCase);
		}

		public Justifier<T1, T2, T3, T4, E> Expect(IExpectation expectation)
		{
			return Expect(new ActionExpectationWrapper<E>(expectation));
		}

		public Justifier<T1, T2, T3, T4, E> Expect(E expected)
		{
			var expectation = new Expectation<E>(expected);
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, E> Expect(E expected, Func<E, E, AssertionResult> asserter)
		{
			var expectation = new AsserterExpectation<E>(expected, asserter);
			return Expect(expectation);
		}
		
		public Justifier<T1, T2, T3, T4, E> Do(Action<E, E> asserter, E expected)
		{
			var expectation = new StandardAssertExpectation<E>(expected, asserter);
			return Expect(expectation);
		}
		
		public Justifier<T1, T2, T3, T4, E> XDo(Action<E, E> asserter, E expected)
		{
			var expectation = new StandardAssertExpectation<E>(asserter, expected);
			return Expect(expectation);
		}		

		public Justifier<T1, T2, T3, T4, E> Do(Action<E> assertion)
		{
			var expectation = new StandardAssertExpectation<E>(assertion);
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, E> Expect(Predicate<E> expected)
		{
			var expectation = new Expectation<E>(expected);
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, E> Expect(Func<T1, T2, T3, T4, E> transform)
		{
			Predicate<E> predicate = actual => Equals(actual, _testCase.G1); 
            return Expect(predicate);
		}

		public Justifier<T1, T2, T3, T4, E> ExpectNull()
		{
			var expectation = new Expectation<E>((E a) => a == null, a => string.Format("Expected null, but got <{0}>", a));
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, E> ExpectNotNull()
		{
			var expectation = new Expectation<E>((E a) => a != null, a => "Expected something no null, but got null");
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, E> ExpectException<TException>()
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>();			
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, E> ExpectException<TException>(string message)
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>(message);			
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, E> ExpectException<TException>(Predicate<TException> predicate)
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>(predicate);			
			return Expect(expectation);
		}		
    }

    public partial class Expector<T1, T2, T3, T4, T5, E>
    {
		private TestCaseCollection<T1, T2, T3, T4, T5, E> _builder;
		ITestCase<T1, T2, T3, T4, T5, E> _testCase;

		public Expector(TestCaseCollection<T1, T2, T3, T4, T5, E> builder, ITestCase<T1, T2, T3, T4, T5, E> testCase)
		{
			_builder = builder;
			_testCase = testCase;
		}		

		public Justifier<T1, T2, T3, T4, T5, E> Expect(IExpectation<E> expectation)
		{
			_testCase.Expectation = expectation;
			return new Justifier<T1, T2, T3, T4, T5, E>(_builder, _testCase);
		}

		public Justifier<T1, T2, T3, T4, T5, E> Expect(IExpectation expectation)
		{
			return Expect(new ActionExpectationWrapper<E>(expectation));
		}

		public Justifier<T1, T2, T3, T4, T5, E> Expect(E expected)
		{
			var expectation = new Expectation<E>(expected);
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, E> Expect(E expected, Func<E, E, AssertionResult> asserter)
		{
			var expectation = new AsserterExpectation<E>(expected, asserter);
			return Expect(expectation);
		}
		
		public Justifier<T1, T2, T3, T4, T5, E> Do(Action<E, E> asserter, E expected)
		{
			var expectation = new StandardAssertExpectation<E>(expected, asserter);
			return Expect(expectation);
		}
		
		public Justifier<T1, T2, T3, T4, T5, E> XDo(Action<E, E> asserter, E expected)
		{
			var expectation = new StandardAssertExpectation<E>(asserter, expected);
			return Expect(expectation);
		}		

		public Justifier<T1, T2, T3, T4, T5, E> Do(Action<E> assertion)
		{
			var expectation = new StandardAssertExpectation<E>(assertion);
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, E> Expect(Predicate<E> expected)
		{
			var expectation = new Expectation<E>(expected);
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, E> Expect(Func<T1, T2, T3, T4, T5, E> transform)
		{
			Predicate<E> predicate = actual => Equals(actual, _testCase.G1); 
            return Expect(predicate);
		}

		public Justifier<T1, T2, T3, T4, T5, E> ExpectNull()
		{
			var expectation = new Expectation<E>((E a) => a == null, a => string.Format("Expected null, but got <{0}>", a));
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, E> ExpectNotNull()
		{
			var expectation = new Expectation<E>((E a) => a != null, a => "Expected something no null, but got null");
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, E> ExpectException<TException>()
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>();			
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, E> ExpectException<TException>(string message)
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>(message);			
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, E> ExpectException<TException>(Predicate<TException> predicate)
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>(predicate);			
			return Expect(expectation);
		}		
    }

    public partial class Expector<T1, T2, T3, T4, T5, T6, E>
    {
		private TestCaseCollection<T1, T2, T3, T4, T5, T6, E> _builder;
		ITestCase<T1, T2, T3, T4, T5, T6, E> _testCase;

		public Expector(TestCaseCollection<T1, T2, T3, T4, T5, T6, E> builder, ITestCase<T1, T2, T3, T4, T5, T6, E> testCase)
		{
			_builder = builder;
			_testCase = testCase;
		}		

		public Justifier<T1, T2, T3, T4, T5, T6, E> Expect(IExpectation<E> expectation)
		{
			_testCase.Expectation = expectation;
			return new Justifier<T1, T2, T3, T4, T5, T6, E>(_builder, _testCase);
		}

		public Justifier<T1, T2, T3, T4, T5, T6, E> Expect(IExpectation expectation)
		{
			return Expect(new ActionExpectationWrapper<E>(expectation));
		}

		public Justifier<T1, T2, T3, T4, T5, T6, E> Expect(E expected)
		{
			var expectation = new Expectation<E>(expected);
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, T6, E> Expect(E expected, Func<E, E, AssertionResult> asserter)
		{
			var expectation = new AsserterExpectation<E>(expected, asserter);
			return Expect(expectation);
		}
		
		public Justifier<T1, T2, T3, T4, T5, T6, E> Do(Action<E, E> asserter, E expected)
		{
			var expectation = new StandardAssertExpectation<E>(expected, asserter);
			return Expect(expectation);
		}
		
		public Justifier<T1, T2, T3, T4, T5, T6, E> XDo(Action<E, E> asserter, E expected)
		{
			var expectation = new StandardAssertExpectation<E>(asserter, expected);
			return Expect(expectation);
		}		

		public Justifier<T1, T2, T3, T4, T5, T6, E> Do(Action<E> assertion)
		{
			var expectation = new StandardAssertExpectation<E>(assertion);
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, T6, E> Expect(Predicate<E> expected)
		{
			var expectation = new Expectation<E>(expected);
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, T6, E> Expect(Func<T1, T2, T3, T4, T5, T6, E> transform)
		{
			Predicate<E> predicate = actual => Equals(actual, _testCase.G1); 
            return Expect(predicate);
		}

		public Justifier<T1, T2, T3, T4, T5, T6, E> ExpectNull()
		{
			var expectation = new Expectation<E>((E a) => a == null, a => string.Format("Expected null, but got <{0}>", a));
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, T6, E> ExpectNotNull()
		{
			var expectation = new Expectation<E>((E a) => a != null, a => "Expected something no null, but got null");
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, T6, E> ExpectException<TException>()
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>();			
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, T6, E> ExpectException<TException>(string message)
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>(message);			
			return Expect(expectation);
		}

		public Justifier<T1, T2, T3, T4, T5, T6, E> ExpectException<TException>(Predicate<TException> predicate)
			where TException : Exception
		{
			var expectation = new ExceptionExpectation<TException>(predicate);			
			return Expect(expectation);
		}		
    }

}
